#include <func.h>
#include "account.h"
#include "client.h"

//在使用之前先创建一个account表，crypy的字符长度尽量长一点，我设置的为varchar(100)
//需要添加这两个头文件
//#include<mysql/mysql.h>
//#include<crypt.h>
//makefile文件需要添加 -lmysqlclient -lcrypt

/* mysql> select * from account;
+----------+--------------+----------------------------------------------------------------------------------------------------+
| user     | salt         | crypt                                                                                              |
+----------+--------------+----------------------------------------------------------------------------------------------------+
| zhangsan | $6$j5khApH7$ | $6$j5khApH7$sdadjkahaa6s65a4asdahdgaj                                                              |
| lisi     | asdasda      | ajhkhk                                                                                             |
| sh     | $6$yBecsu8s$ | $6$yBecsu8s$e6yeT9XNzyUlPsFtCR8zOLun/W88f8RSqO5MBhLXV7lz87V8tNzPOYa0YEYeG02sLxFBOOGoj6HPn3kQ6NRlh. |
| shuai    | $6$A8I5q6MX$ | $6$A8I5q6MX$EccBv7SaIKLB06QVGn5/CHZPjS2ZoTMkEhj/IwAidycdsAYA2xr1wurfTl6fkA2oOFaHUT2nDOB084AvGJHU4/ |
+----------+--------------+----------------------------------------------------------------------------------------------------+ */

//产生随机盐值，用二级指针来传入传出生成的盐值
int randSalt(char **salt){
    //salt的格式为 $6$ + 8个随机字符 + $
    srand(time(NULL));//通过时间函数设置随机
    char str[SALTLEN] = {0};
    //生成8个随机字符
    for(int i = 0;i < SALTLEN; i++){
        int flag = rand() %3;
        switch (flag)
        {
        case 0:
            str[i] = rand()%26 + 'A';
            break;
        case 1:
            str[i] = rand()%26 + 'a';
            break;
        case 2:
            str[i] = rand()%10 + '0';
            break;
        default:
            break;
        }
    }
    //拼接一下
    strcpy(*salt,"$6$");
    strcat(*salt,str);
    strcat(*salt,"$");
}

int getSaltCrypt(char *name,char **salt,char **crypt){
    //进入对应数据库
    MYSQL *db = mysql_init(NULL);
    char * host = "localhost";
    char * user = "root";//mysql账号名
    char * password = "123";//账号密码
    char * database = "netDisk";//提前生成好的数据库，改为自己的数据库即可
    MYSQL * ret = mysql_real_connect(db,host,user,password,database,0,NULL,0);//进入数据库
    if(ret != 0){
        //printf("db = %p,ret = %p\n",db,ret);
        printf("successed\n");
    }
    else{
        printf("error: %s\n",mysql_error(db));
        exit(-1);
    }
    //在表account中查找用户名为name的salt与crypt
    char sql[300] = "select salt,crypt from account where user = ";
    strcat(sql,"'");
    strcat(sql,name);
    strcat(sql,"'");
    int qret = mysql_query(db,sql);//执行对应语句
    if(qret != 0){
        printf("error: %s\n",mysql_error(db));
        exit(-1);
    }
    //读取刚才执行语句的结果字符串
    MYSQL_RES *result = mysql_store_result(db);
    //printf("the row number = %ld\n",mysql_num_rows(result));
    MYSQL_ROW  row;
    //一行一行的读取,
    if((row = mysql_fetch_row(result)) != NULL){
            strcpy(*salt,row[0]);//将盐值传入到*salt中
            strcpy(*crypt,row[1]);//将密文传入到*crypt中
    }
    mysql_free_result(result);
    mysql_close(db);
}

//保存操作和获取操作类似
int saveSaltCrypt(char *name,char *salt,char *crypt){
    //进入对应数据库
    MYSQL *db = mysql_init(NULL);
    char * host = "localhost";
    char * user = "root";
    char * password = "123";
    char * database = "netDisk";
    MYSQL * ret = mysql_real_connect(db,host,user,password,database,0,NULL,0);
    if(ret != 0){
        printf("db = %p,ret = %p\n",db,ret);
        printf("successed\n");
    }
    else{
        printf("error: %s\n",mysql_error(db));
        exit(-1);
    }
    //拼接插入执行语句
    char str[50] = "insert into account values";
    char sql[300] = {0};
    sprintf(sql,"%s ('%s','%s','%s')",str,name,salt,crypt);
    //执行插入语句
    int qret = mysql_query(db,sql);
    if(qret != 0){
        printf("error: %s\n",mysql_error(db));
        exit(-1);
    }
    mysql_close(db);
}

//服务端登录函数
int loadSever(int netFd){
    int length;
    //接收账号名字
    char name[50] = {0};
    recv(netFd,&length,sizeof(int),0);
    recv(netFd,name,length,0);
    puts(name);
    char pwd[50] = {0};
    //接收账号密码
    recv(netFd,&length,sizeof(int),0);
    recv(netFd,pwd,length,0);
    puts(pwd);
    //在堆上申请一片空间，用来存储salt以及cryp
    char *salt = (char *)calloc(50,sizeof(char));
    char *cryp = (char *)calloc(100,sizeof(char));
    char buf[30] = {0};
    //通过用户名来查找对应账号的盐值与密文，并通过二级指针传回来
    getSaltCrypt(name,&salt,&cryp);
    //crypy函数可以根据pwd与salt生成一段密文，其返回字符串就是密文
    //用客户端发送过来的pwd与数据库存储该用户生成的密文和数据库存储的密文比对，相同则正常登录
    if(strcmp(cryp,crypt(pwd,salt)) == 0){
        strcpy(buf,"true");
    }
    else{
        strcpy(buf,"false");
    }
    free(salt);
    free(cryp);
    //发送给客户端是否成功登录
    send(netFd,buf,strlen(buf),0);
}

//客户端登录函数
int loadClient(int netFd){
  //登录模块
    train_t t;
    bool across = false;
    do{
        char name[50] = {0};
        printf("请输入账号名称: ");
        scanf("%s",name);
        char pwd[1024]={0};
        printf("请输入服务器密码: ");
        int i;
        scanf("%s",pwd);
        char rbuf[50]  ={0};
        //发送账号名称
        bzero(&t,sizeof(t));
        t.dataLength = strlen(name);
        strcpy(t.buf,name);
        send(netFd,&t,sizeof(t.dataLength) + t.dataLength,0);
        //发送账号密码
        bzero(&t,sizeof(t));
        t.dataLength = strlen(pwd);
        strcpy(t.buf,pwd);
        send(netFd,&t,sizeof(t.dataLength) + t.dataLength,0);
        //接收是否成功登录消息
        recv(netFd,rbuf,sizeof(rbuf),0);
        if(across == false){
            if(strcmp("true",rbuf)==0){
                across = true;
                puts("成功登录！");
            }
            else{
                puts("账号名称错误或密码错误");
                while(1){
                    puts("1.继续登录");
                    puts("2.注册账号");
                    puts("3.退出");
                    int num;
                    scanf("%d",&num);
                    if(num == 1){
                        break;
                    }
                    else if(num == 2){
                        signIn(netFd);
                        break;
                    }
                    else if(num == 3){
                        puts("欢迎下次使用！");
                        exit(0);
                    }
                    else{
                        puts("错误指令，请重新输入");
                    }
                }
            }
        }
    }while(across == false); //登录判断
}

int signIn(int netFd){
    printf("请输入账号名称: ");
    char name[50] = {0};
    scanf("%s",name);
    printf("请输入账号密码: ");
    char pwd[50] = {0};
    scanf("%s",pwd);
    char *salt = (char *)calloc(30,sizeof(char));
    randSalt(&salt);
    //名字，盐值，生成的密文保存到数据库中
    saveSaltCrypt(name,salt,crypt(pwd,salt));
    printf("注册成功\n");
    free(salt);
}
